//
//  fraction.c
//  linear_algebra
//
//  Created by zhangnan on 2025/3/31.
//

#include "fraction.h"

#include <stdlib.h>
#include <stdio.h>
#include "../utils/common.h"


// 释放分数对象所占用的内存
void free_fraction(FRACTION_TYPE *f) {
    if (f != NULL) {
        free(f);
    }
}

// 创建一个新的分数对象，并分配内存
// 参数a: 分子
// 参数b: 分母
// 返回值: 指向新创建的分数对象的指针
FRACTION_TYPE *new_fraction(int a, int b) {
    if (b == 0) {
        fprintf(stderr, "Error: Denominator cannot be zero.\n");
        return NULL;
    }

    FRACTION_TYPE *f = (FRACTION_TYPE *)malloc(sizeof(FRACTION_TYPE));
    if (f == NULL) {
        fprintf(stderr, "Error: Memory allocation failed.\n");
        return NULL;
    }

    f->numerator = a;
    f->denominator = b;

    return simplify(f); // 自动简化分数
}

// 创建一个新的简化分数对象，并分配内存
// 参数a: 分子，分母默认为1
// 返回值: 指向新创建的简化分数对象的指针
FRACTION_TYPE *new_simple_fraction(int a) {
    return new_fraction(a, 1);
}

// 简化分数
// 参数f: 需要简化的分数指针
// 返回值: 指向简化后的分数对象的指针
FRACTION_TYPE *simplify(FRACTION_TYPE *f) {
    if (f == NULL) {
        fprintf(stderr, "Error: Null pointer passed to simplify.\n");
        return NULL;
    }

    int divisor = gcd(abs(f->numerator), abs(f->denominator));
    f->numerator /= divisor;
    f->denominator /= divisor;

    if (f->denominator < 0) { // 确保分母为正
        f->numerator = -f->numerator;
        f->denominator = -f->denominator;
    }

    return f;
}

// 分数加法
// 参数f1: 第一个分数
// 参数f2: 第二个分数
// 返回值: 指向两个分数相加结果的分数对象的指针
FRACTION_TYPE *add_fractions(FRACTION_TYPE *f1, FRACTION_TYPE *f2) {
    if (f1 == NULL || f2 == NULL) {
        fprintf(stderr, "Error: Null pointer passed to add_fractions.\n");
        return NULL;
    }

    int numerator = f1->numerator * f2->denominator + f2->numerator * f1->denominator;
    int denominator = f1->denominator * f2->denominator;

    return new_fraction(numerator, denominator);
}

// 分数减法
// 参数f1: 第一个分数
// 参数f2: 第二个分数
// 返回值: 指向两个分数相减结果的分数对象的指针
FRACTION_TYPE *sub_fractions(FRACTION_TYPE *f1, FRACTION_TYPE *f2) {
    if (f1 == NULL || f2 == NULL) {
        fprintf(stderr, "Error: Null pointer passed to sub_fractions.\n");
        return NULL;
    }

    int numerator = f1->numerator * f2->denominator - f2->numerator * f1->denominator;
    int denominator = f1->denominator * f2->denominator;

    if(numerator == 0){
        return new_simple_fraction(0);
    }

    return new_fraction(numerator, denominator);
}

// 分数乘法
// 参数f1: 第一个分数
// 参数f2: 第二个分数
// 返回值: 指向两个分数相乘结果的分数对象的指针
FRACTION_TYPE *multi_fractions(FRACTION_TYPE *f1, FRACTION_TYPE *f2) {
    if (f1 == NULL || f2 == NULL) {
        fprintf(stderr, "Error: Null pointer passed to multi_fractions.\n");
        return NULL;
    }

    int numerator = f1->numerator * f2->numerator;
    int denominator = f1->denominator * f2->denominator;

    return new_fraction(numerator, denominator);
}

// 分数除法
// 参数f1: 第一个分数
// 参数f2: 第二个分数
// 返回值: 指向两个分数相除结果的分数对象的指针
FRACTION_TYPE *divide_fractions(FRACTION_TYPE *f1, FRACTION_TYPE *f2) {
    if (f1 == NULL || f2 == NULL) {
        fprintf(stderr, "Error: Null pointer passed to divide_fractions.\n");
        return NULL;
    }

    if (f2->numerator == 0) {
        fprintf(stderr, "Error: Division by zero in divide_fractions.\n");
        return NULL;
    }

    int numerator = f1->numerator * f2->denominator;
    int denominator = f1->denominator * f2->numerator;

    return new_fraction(numerator, denominator);
}
